#pragma once

#include <iostream>
#include <vector>

namespace mian_yang
{
#define DEFAULT_BUFFER_SIZE (10 * 1024 * 1024)
#define THRESHOLD_BUFFER_SIZE (8 * 1024 * 1024)
#define INCREMENT_BUFFER_SIZE (1 * 1024 * 1024)
    class Buffer
    {
    public:
        Buffer()
            : _buffer(DEFAULT_BUFFER_SIZE),
              _writer_idx(0),
              _reader_idx(0)
        {}

        /*向缓冲区中写入数据*/
        void push(const char* data, size_t len)
        {
            /*要注意缓冲区剩余空间不够大情况
            1、扩容。 2、阻塞
            固定大小， 就直接返回， 否则扩容*/
            if (len > WriteAbleSize())
            {

                return;
            }
            // ensureEoughSize(len);   

            /*1、将数据拷贝进入缓冲区*/
            std::copy(data, data + len, &_buffer[_writer_idx]);
            /*这里是将data的数据拷贝到_buffer中*/
            moveWriter(len);
        }

        const char* begin()
        {
            /*返回可读数据的起始地址*/
            return &_buffer[_reader_idx];
        }

        size_t readAbleSize()
        {
            /*
                因为当前实现的缓冲区设计思想是双缓冲区。
                所以处理完就叫唤， 不会存在空间循环使用
                的情况。
            */
            return _writer_idx - _reader_idx;
        }
        /*返回可以写的长度*/
        size_t WriteAbleSize()
        {
            /*
                对于扩容思路来说， 不存在可写的空间大小，
                总是可写， 因此这个接口仅仅对固定大小缓
                冲区提供。
            */
           return (_buffer.size() - _writer_idx);
        }

        /*对于读指针进行向后遍历的操作*/
        void moveReader(size_t len)
        {
            if (len <= readAbleSize())
            {
                _reader_idx += len;
            }
            else 
            {
                std::cout << "空间大小不足， 异步读取失败" << std::endl;
                return;
            }
        }

        /*初始化缓冲区的操作， 重置的读写位置*/
        void reset()
        {
            /*read和write相等表示没有数据可以读取， write为0
            表示所有空间都是空闲的。*/
            _reader_idx = _writer_idx = 0;
        }

        void swap(Buffer& buffer)
        {
            _buffer.swap(buffer._buffer);
            std::swap(_reader_idx, buffer._reader_idx);
            std::swap(_writer_idx, buffer._writer_idx);
        }

        /*判断缓冲区是否满了*/
        bool empty()
        {
            return (_reader_idx == _writer_idx);
        }
    private:
        /*对空间进行扩容*/
        void ensureEoughSize(size_t len)
        {
            /*不需要扩容的情况， 就是len还小*/
            if (len <= WriteAbleSize()) return;
            size_t new_size = 0;
            if (_buffer.size() < THRESHOLD_BUFFER_SIZE)
            {
                /*小于一个阈值， 就增长翻倍*/
                new_size = _buffer.size() * 2 + len; 
            }
            else 
            {
                /*大于等于阈值了， 就直接线性增长就行*/
                new_size  = _buffer.size() + INCREMENT_BUFFER_SIZE;
            }

            _buffer.resize(new_size);
        }

        /*对于写指针进行向后遍历操作*/
        void moveWriter(size_t len)
        {
            if ((_writer_idx + len) <= _buffer.size())
            {
                _writer_idx += len;
            } 
            else
            {
                std::cout << "异步写入失败" << std::endl;
            }
        }


    private:
        /*信息缓冲区， 这个缓冲区使用数组来实现， 为的是
        不进行频繁创建删除节点的情况下使用队列*/
        std::vector<char> _buffer;
        /*当前可以读取的指针， 本质就是下标， 也就是为尾指针*/
        size_t _reader_idx;
        /*当前可以写入到指针， 本质就是下标， 也就是为头指针*/
        size_t _writer_idx;
    };

}